package com.kacheap.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import com.kacheap.data.enums.OrderStatus;
import com.kacheap.data.enums.OrderStatusChangeEvent;
import com.kacheap.data.pojo.Order;
import com.kacheap.service.IOrderService;

@Service
public class OrderServiceImpl implements IOrderService {
	private int id = 1;

	private Map<Integer, Order> orders = new HashMap<>();

	@Autowired
	private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;

	@Autowired
	private StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;

	public Map<Integer, Order> getOrders() {
		return orders;
	}

	public Order create() {
		Order order = new Order();
		order.setStatus(OrderStatus.WAIT_PAYMENT);
		order.setId(id++);
		orders.put(order.getId(), order);
		return order;
	}

	public Order pay(int id) {
		return this.sendEvent(OrderStatusChangeEvent.PAYED, id);
	}

	public Order deliver(int id) {
		return this.sendEvent(OrderStatusChangeEvent.DELIVERY, id);
	}

	public Order receive(int id) {
		return this.sendEvent(OrderStatusChangeEvent.RECEIVED, id);
	}

	@Override
	public Order refund(int id) {
		return this.sendEvent(OrderStatusChangeEvent.REFUND, id);
	}

	private Order sendEvent(OrderStatusChangeEvent event, int id) {
		Order order = orders.get(id);

		Message<OrderStatusChangeEvent> message = MessageBuilder.withPayload(event).setHeader("order", order).build();

		boolean success = sendEvent(message, order);

		if (success) {
			System.out.println(event.name() + " 操作成功，订单号：" + id);
		} else {
			System.out.println(event.name() + " 操作失败，订单号：" + id);
		}

		return orders.get(id);

	}

	/**
	 * 发送订单状态转换事件
	 *
	 * @param message
	 * @param order
	 * @return
	 */
	private synchronized boolean sendEvent(Message<OrderStatusChangeEvent> message, Order order) {
		boolean result = false;
		try {
			orderStateMachine.start();

			// 尝试恢复状态机状态
			persister.restore(orderStateMachine, order);

			result = orderStateMachine.sendEvent(message);

			if (result) {
				// 持久化状态机状态
				persister.persist(orderStateMachine, order);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			orderStateMachine.stop();
		}
		return result;
	}
}